package com.yyl.rbacs.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yyl.rbacs.annotation.OperationLog;
import com.yyl.rbacs.sys.entity.SysDept;
import com.yyl.rbacs.sys.entity.SysRole;
import com.yyl.rbacs.sys.entity.SysRoleDept;
import com.yyl.rbacs.sys.entity.SysRoleMenu;
import com.yyl.rbacs.sys.mapper.SysRoleMapper;
import com.yyl.rbacs.sys.service.ISysDeptService;
import com.yyl.rbacs.sys.service.ISysRoleDeptService;
import com.yyl.rbacs.sys.service.ISysRoleMenuService;
import com.yyl.rbacs.sys.service.ISysRoleService;
import com.yyl.rbacs.utils.PageQueryUtil;
import com.yyl.rbacs.utils.PageVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色 服务实现类
 * </p>
 *
 * @author YuanSir
 * @since 2022-10-28
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {
    
    
    @Autowired
    private ISysDeptService deptService;
    
    
    @Autowired
    private ISysRoleMenuService roleMenuService;
    
    
    @Autowired
    private ISysRoleDeptService roleDeptService;
    
    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public PageVo queryPage(Map<String, String> params) {
    
        Page<SysRole> sysRolePage = PageQueryUtil.getPage(params);
    
        
        // 2. 创建查询对象
        LambdaQueryWrapper<SysRole> sysRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
    
        String roleName = params.get("roleName");
    
        sysRoleLambdaQueryWrapper
                .eq(StringUtils.isNotBlank(roleName), SysRole::getRoleName, roleName);
    
        page(sysRolePage, sysRoleLambdaQueryWrapper);
    
        //List<SysDept>-->Map<部门id，部门名称>
        HashMap<Long, String> deptMap = new HashMap<>();
        
        //把所有user对象中的deptName进行赋值
        List<SysDept> deptList = deptService.list();
    
        deptList.forEach(sysDept -> deptMap.put(sysDept.getDeptId(),sysDept.getName()));

        //遍历sysUserPage 进行部门名称赋值
        sysRolePage.getRecords().forEach(sysRole -> sysRole.setDeptName(deptMap.get(sysRole.getDeptId())));
        
        return new PageVo<>(sysRolePage);
    }
    
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperationLog("新增角色操作")
    public void saveRole(SysRole sysRole) {
        
        //1.保存角色基本信息
        sysRole.setCreateTime(new Date());
        
        save(sysRole);
        
        //获取主键回填产生的roleId
        
        //2.保存角色和菜单的对应关系
        List<Long> menuIdList = sysRole.getMenuIdList();
        
        //List<菜单ID> ——> List<SysRoleMenu>
        List<SysRoleMenu> sysRoleMenuList = menuIdList
                .stream()
                .map(menuId -> new SysRoleMenu(sysRole.getRoleId(), menuId))
                .collect(Collectors.toList());
    
        roleMenuService.saveBatch(sysRoleMenuList);
        
        //3.保存角色和部门的对应关系
        List<Long> deptIdList = sysRole.getDeptIdList();
    
        List<SysRoleDept> sysRoleDeptList = deptIdList
                .stream()
                .map(deptId -> new SysRoleDept(sysRole.getRoleId(), deptId))
                .collect(Collectors.toList());
    
        roleDeptService.saveBatch(sysRoleDeptList);
        
    }
    
    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public SysRole getRoleById(Long roleId) {
    
        //1.查询角色基本信息
        SysRole role = getById(roleId);
        
        //2.查询角色对应的菜单信息
        List<Long> menuIdList = roleMenuService.listObjs(
                        new LambdaQueryWrapper<SysRoleMenu>()
                                .select(SysRoleMenu::getMenuId)
                                .eq(SysRoleMenu::getRoleId, roleId))
                .stream()
                .map(o -> (Long) o)
                .collect(Collectors.toList());
        
        role.setMenuIdList(menuIdList);
        
        //3.查询角色对应的部门信息
        List<Long> deptIdList = roleDeptService.listObjs(
                        new LambdaQueryWrapper<SysRoleDept>()
                                .select(SysRoleDept::getDeptId)
                                .eq(SysRoleDept::getRoleId, roleId))
                .stream()
                .map(o -> (Long) o)
                .collect(Collectors.toList());
    
        role.setDeptIdList(deptIdList);
    
        return role;
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    @OperationLog("更新角色操作")
    public void updateRole(SysRole sysRole) {
        
        //1.更新角色基本信息，sys_role
        updateById(sysRole);
        
        //2.更新 sys_role_menu
        //2.1先删除该角色对应的 sys_role_menu 表中的数据
        roleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getRoleId, sysRole.getRoleId()));
        
        roleDeptService.remove(new LambdaQueryWrapper<SysRoleDept>()
                .eq(SysRoleDept::getRoleId, sysRole.getRoleId()));
        
        //2.2再重新插入
        //List<菜单ID> ——> List<SysRoleMenu>
        List<Long> menuIdList = sysRole.getMenuIdList();
        
        List<SysRoleMenu> sysRoleMenuList = menuIdList
                .stream()
                .map(menuId -> new SysRoleMenu(sysRole.getRoleId(), menuId))
                .collect(Collectors.toList());
        roleMenuService.saveBatch(sysRoleMenuList);
        
        //3.更新 sys_role_dept
        List<Long> deptIdList = sysRole.getDeptIdList();
    
        List<SysRoleDept> sysRoleDeptList = deptIdList
                .stream()
                .map(deptId -> new SysRoleDept(sysRole.getRoleId(), deptId))
                .collect(Collectors.toList());
    
        roleDeptService.saveBatch(sysRoleDeptList);
    }
    
}
